package com.gupao.vip.aio;

import cn.hutool.core.util.StrUtil;
import org.apache.commons.io.IOUtils;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;

public class ReadCompletionHandler implements CompletionHandler<Integer, ByteBuffer> {
    private AsynchronousSocketChannel channel;

    public ReadCompletionHandler(AsynchronousSocketChannel channel){
        if(Objects.isNull(this.channel)){
            this.channel = channel;
        }
    }

    /**
     * 读取到消息后的处理
     * @param result
     * @param attachment
     */
    @Override
    public void completed(Integer result, ByteBuffer attachment) {
        //为后续从缓冲区读取数据做准备
        attachment.flip();

        //根据缓冲区的可读字节数创建byte数组
        byte[] body = new byte[attachment.remaining()];
        attachment.get(body);
        try{
            String req = new String(body, "UTF-8");
            System.out.println("The time server receive order : " + req);
            String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(req) ? LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME) : "BAD ORDER";
            doWrite(currentTime);
        }catch(UnsupportedEncodingException e){
            System.err.println(e.getMessage());
        }
    }

    @Override
    public void failed(Throwable exc, ByteBuffer attachment) {
        IOUtils.closeQuietly(channel);
    }

    private void doWrite(String currentTime){
        if(StrUtil.isNotEmpty(currentTime)){
            byte[] bytes = currentTime.getBytes();
            ByteBuffer writeBuffer = ByteBuffer.allocate(bytes.length);
            writeBuffer.put(bytes);
            writeBuffer.flip();

            //主要用于读取半包消息和发送应答
            channel.write(writeBuffer, writeBuffer, new CompletionHandler<Integer, ByteBuffer>() {
                @Override
                public void completed(Integer result, ByteBuffer attachment) {
                    //如果没有发送完成，继续发送
                    channel.write(attachment, attachment, this);
                }

                @Override
                public void failed(Throwable exc, ByteBuffer attachment) {
                    IOUtils.closeQuietly(channel);
                }
            });
        }
    }
}
